package com.gitee.fsmxm.ocon.model;

import com.gitee.fsmxm.ocon.core.Pool;
import com.gitee.fsmxm.ocon.util.WinTaskUtils;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @author fsmxm
 * @date 2019/10/9
 */
public class Procedure {
    private static final Logger LOGGER = LoggerFactory.getLogger(Procedure.class);
    public static final int STATUS_IDEL = 0;
    public static final int STATUS_BUSY = 1;


    /**
     * word excel powerpoint application process
     */
    private ActiveXComponent application;

    /**
     * documents workbooks presentations process
     */
    private Dispatch dispatch;

    /**
     * component process pid
     */
    private int componentPid;

    /**
     * word excel powerpoint
     */
    private String appName;

    /**
     * convert start time
     */
    private long startTime = -1;

    /**
     * 状态 0-空闲 1-占用
     */
    private volatile int status = 0;

    /**
     * task
     */
    private Task task;

    /**
     * pool
     */
    private Pool<Procedure> pool;

    public Procedure(ActiveXComponent application, Dispatch dispatch) {
        this.application = application;
        this.dispatch = dispatch;
    }

    public ActiveXComponent getApplication() {
        return application;
    }

    public void setApplication(ActiveXComponent application) {
        this.application = application;
    }

    public Dispatch getDispatch() {
        return dispatch;
    }

    public void setDispatch(Dispatch dispatch) {
        this.dispatch = dispatch;
    }

    public int getComponentPid() {
        return componentPid;
    }

    public void setComponentPid(int componentPid) {
        this.componentPid = componentPid;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    public Task getTask() {
        return task;
    }

    public void setTask(Task task) {
        this.task = task;
    }

    public Pool<Procedure> getPool() {
        return pool;
    }

    public void setPool(Pool<Procedure> pool) {
        this.pool = pool;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    /**
     * 释放，放回进程池
     */
    public void release() {
        pool.retrieve(this);
    }

    public void close() {
        try {
            application.invoke("Quit", new Variant[]{});
            dispatch.safeRelease();
            application.safeRelease();
        } catch (Exception e) {
            LOGGER.warn("Close procedure failed, try to kill process. failed procedure: {}", this);
            try {
                String[] result = WinTaskUtils.forceKillAll(componentPid);
                LOGGER.info("Success: {}, error: {}", result[0], result[1]);
            } catch (IOException ex) {
                LOGGER.warn("Exception: ", ex);
            }
        }
    }

    @Override
    public String toString() {
        return "Procedure{" +
                "component=" + application +
                ", dispatches=" + dispatch +
                ", componentPid=" + componentPid +
                ", appName='" + appName + '\'' +
                ", startTime=" + startTime +
                ", task=" + task +
                ", poolName=" + pool.name() +
                '}';
    }
}
